﻿using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Caching.Memory;

namespace WAU.Common
{
    /// <summary>
    /// 供组件使用的缓存
    /// </summary>
    public class CacheForComponent
    {
        /// <summary>
        /// 用于标记来源的标签
        /// </summary>
        private string cacheTag;

        /// <summary>
        /// IDistributedCache 实现
        /// </summary>
        private readonly IDistributedCache cacheImpl;

        /// <summary>
        /// ctor
        /// </summary>
        /// <param name="cacheTag"></param>
        /// <param name="cacheImpl"></param>
        public CacheForComponent(string cacheTag, IDistributedCache cacheImpl)
        {
            this.cacheTag = cacheTag + ":";
            this.cacheImpl = cacheImpl;
        }

        /// <summary>
        /// 设置缓存（无过期时间）
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public void SetCache(string key, object value)
        {
            if(value is not int && value is not string)
            {
                throw new Exception("CacheForComponent 仅接受 类型为 int 或 string 的 value");
            }

            cacheImpl.SetString(cacheTag + key, value.ToString(), new DistributedCacheEntryOptions { });
        }

        //  SlidingExpiration 表示最后一次访问多长时间以后可以被删除
        //  AbsoluteExpiration 表示绝对过期时间
        //  AbsoluteExpirationRelativeToNow 表示相对过期时间

        /// <summary>
        /// 设置缓存（带滑动过期时间）
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="timeSpan"></param>
        public void SetCacheSlideExpire(string key, object value, TimeSpan timeSpan)
        {
            if (value is not int && value is not string)
            {
                throw new Exception("CacheForComponent 仅接受 类型为 int 或 string 的 value");
            }

            cacheImpl.SetString(cacheTag + key, value.ToString(), new DistributedCacheEntryOptions
            {
                SlidingExpiration = timeSpan
            });
        }

        /// <summary>
        /// 设置缓存（带绝对过期时间）
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="absoluteExpiration"></param>
        /// <returns></returns>
        public void SetCacheAbsoluteExpire(string key, object value, DateTimeOffset absoluteExpiration)
        {
            if (value is not int && value is not string)
            {
                throw new Exception("CacheForComponent 仅接受 类型为 int 或 string 的 value");
            }

            cacheImpl.SetString(cacheTag + key, value.ToString(), new DistributedCacheEntryOptions 
            { 
                AbsoluteExpiration = absoluteExpiration 
            });
        }

        /// <summary>
        /// 设置缓存（相对过期时间）
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="absoluteExpirationRelativeToNow"></param>
        /// <returns></returns>
        public void SetCacheAbsoluteExpire(string key, object value, TimeSpan absoluteExpirationRelativeToNow)
        {
            if (value is not int && value is not string)
            {
                throw new Exception("CacheForComponent 仅接受 类型为 int 或 string 的 value");
            }

            cacheImpl.SetString(cacheTag + key, value.ToString(), new DistributedCacheEntryOptions
            {
                AbsoluteExpirationRelativeToNow = absoluteExpirationRelativeToNow
            });
        }

        /// <summary>
        /// 读取缓存
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public bool TryGetCacheValue(string key, out int value)
        {
            string vTemp = cacheImpl.GetString(cacheTag + key);
            if (vTemp == null)
            {
                value = 0;
                return false;
            }
            else
            {
                return int.TryParse(vTemp, out value);
            }
        }

        /// <summary>
        /// 读取缓存
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public bool TryGetCacheValue(string key, out string value)
        {
            string vTemp = cacheImpl.GetString(cacheTag + key);
            if (vTemp == null)
            {
                value = null;
                return false;
            }
            else
            {
                value = vTemp;
                return true;
            }            
        }

        

        /// <summary>
        /// 删除缓存
        /// </summary>
        /// <param name="key"></param>
        public void RemoveCache(string key)
        {
            cacheImpl.Remove(cacheTag + key);
        }
    }
}
